﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using Microsoft.Win32;

namespace IEProxy.Net
{
    public partial class Form1 : Form
    {
        #region Attributes

        private string xmlPath =""; 

        private Size BtnSize = new Size(130, 25); //按钮Size
        private Point p = new Point(60,70); //按钮起始坐标
        private int h = 50; //按钮坐标高度间隔大小;

        private static List<Proxy> PublicProxy = new List<Proxy>();
        private static List<Proxy> PrivateProxy = new List<Proxy>();
        private static Proxy CurrentProxy = new Proxy();
        private static string ProxyStatus = "0";

        private const int INTERNET_OPTION_SETTINGS_CHANGED = 37;
        private const int INTERNET_OPTION_REFRESH = 39;

        private List<Button> button = new List<Button>();

        #endregion

        #region Form

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                xmlPath = ConfigurationManager.AppSettings["server"];
                if (xmlPath == null)
                {
                    MessageBox.Show("请配置服务器文件地址");
                    Application.Exit();
                    return;
                }
            }
            catch (ConfigurationErrorsException)
            {
                MessageBox.Show("请检查配置文件");
                return;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }

            InitForm();
        }

        private void Form1_SizeChanged(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.notifyIcon1.Visible = true;
                this.Hide();
            }
            else
            {
                lblProxyStatus_SizeChanged(sender, e);
            }
        }

        private void InitForm()
        {
            ShowProxy();
            LoadProxy(0);
            DrawProxy();
        }

        #endregion

        #region notifyIcon

        private void notifyIcon1_DoubleClick(object sender, EventArgs e)
        {
            this.Visible = true;
            this.WindowState = FormWindowState.Normal;
        }

        #endregion

        #region ProxySetting

        /// <summary>
        /// 显示当前代理服务器
        /// </summary>
        private void ShowProxy()
        {
            //打开注册表
            RegistryKey regKey = Registry.CurrentUser;
            string SubKeyPath = @"Software\Microsoft\Windows\CurrentVersion\Internet Settings";
            RegistryKey optionKey = regKey.OpenSubKey(SubKeyPath, true);
            if (optionKey == null)
            {
                MessageBox.Show(@"注册表损坏，请修复\nHKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings");
                return;
            }

            //获取键值
            ProxyStatus = "0";
            CurrentProxy.name = "";
            try
            {

                ProxyStatus = optionKey.GetValue("ProxyEnable").ToString();
                CurrentProxy.name = optionKey.GetValue("ProxyName").ToString();
            }
            catch
            {

            }

            if (ProxyStatus == "1")
            {
                this.lblProxyStatus.Text = CurrentProxy.name;
                this.ToolStripMenuItem_ViewProxy.Text = "当前：" + CurrentProxy.name;
                this.ToolStripMenuItem_ViewProxy2.Text = "当前：" + CurrentProxy.name;
                this.notifyIcon1.ShowBalloonTip(3000, "友情提示", "当前代理服务器：" + CurrentProxy.name, ToolTipIcon.Info);
            }
            else
            {
                this.lblProxyStatus.Text = "代理已关闭";
                this.ToolStripMenuItem_ViewProxy.Text = "代理已关闭";
                this.ToolStripMenuItem_ViewProxy2.Text = "代理已关闭";
                this.notifyIcon1.ShowBalloonTip(3000, "友情提示", "代理功能已关闭", ToolTipIcon.Info);
            }
        }

        /// <summary>
        /// 加载服务器端设置
        /// </summary>
        /// <returns></returns>
        private bool LoadProxy(int num)
        {
            bool b = true;
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(xmlPath);

                #region 公共配置

                XmlAttribute xa = doc.SelectSingleNode("/configuration/public/proxy").Attributes["exception"];
                string publicRule = xa == null ? "" : xa.Value;
                XmlNodeList xnl = doc.SelectNodes("/configuration/public/proxy/server");
                foreach (XmlNode xn in xnl)
                {
                    Proxy proxy = new Proxy();
                    proxy.name = xn.Attributes["name"].Value;
                    proxy.ip = xn.Attributes["ip"].Value;
                    proxy.filter = xn.Attributes["exception"] == null ? publicRule : xn.Attributes["exception"].Value;
                    PublicProxy.Add(proxy);
                }

                #endregion

                #region 私有配置

                PrivateProxy = PublicProxy;
                List<string> mac = GetMacAddress();
                XmlNodeList computers = doc.SelectNodes("/configuration/private/computer");
                foreach (XmlNode computer in computers)
                {
                    if (mac.Contains(computer.Attributes["mac"].Value.ToUpper()))
                    {
                        xa = computer.Attributes["exception"];
                        string privateRule = xa == null ? "" : publicRule;
                        xnl = computer.SelectNodes("proxy");
                        if (xnl.Count > 0)
                        {
                            PrivateProxy.Clear();
                            foreach (XmlNode xn in xnl)
                            {
                                Proxy proxy = new Proxy();
                                proxy.name = xn.Attributes["name"].Value;
                                proxy.ip = xn.Attributes["ip"].Value;
                                proxy.filter = xn.Attributes["exception"] == null ? privateRule : xn.Attributes["exception"].Value;
                                PrivateProxy.Add(proxy);
                            }
                        }
                    }
                }

                #endregion
            }
            catch (DirectoryNotFoundException)
            {
                b = false;
                MessageBox.Show("服务器连接失败");
            }
            catch
            {
                num++;
                if (num < 5) LoadProxy(num);
                else
                {
                    b = false;
                    MessageBox.Show("配置获取错误，请检查服务器设置");
                }
            }
            return b;
        }

        /// <summary>
        /// 绘制代理选项按钮
        /// </summary>
        /// <returns></returns>
        private bool DrawProxy()
        {
            bool b = true;
            int i = 0;

            try
            {
                foreach (Proxy proxy in PrivateProxy)
                {
                    #region Form

                    Button btn = new Button();
                    try
                    {
                        btn.Name = proxy.name;
                        btn.AccessibleName = proxy.name;
                        if (ProxyStatus == "1" && CurrentProxy.name == proxy.name)
                        {
                            btn.Text = "关闭" + btn.AccessibleName;
                        }
                        else
                        {
                            btn.Text = "启用" + btn.AccessibleName;
                        }
                        btn.Click += new EventHandler(Button_Click);
                        btn.Size = BtnSize;
                        btn.Location = new Point(p.X, p.Y + h * i);
                        this.Controls.Add(btn);
                        this.Height += h;

                        button.Add(btn);
                    }
                    catch
                    {
                        btn.Dispose();
                    }

                    #endregion

                    #region notifyIcon

                    ToolStripMenuItem item=null;
                    try
                    {
                        item = new ToolStripMenuItem("启用" + proxy.name, null, ToolStripMenuItem_Click, proxy.name);
                        if (ProxyStatus == "1" && CurrentProxy.name == proxy.name)
                        {
                            item.Text = "关闭" + proxy.name;
                        }
                        this.ToolStripMenuItem_Setting.DropDownItems.Add(item);
                    }
                    catch
                    {
                        item.Dispose();
                    }

                    #endregion

                    i++;
                }
            }
            catch
            {
                b = false;
            }

            return b;
        }

        /// <summary>
        /// 设置代理服务器
        /// </summary>
        /// <param name="proxy"></param>
        private void SetProxy(Proxy proxy)
        {
            //打开注册表
            RegistryKey regKey = Registry.CurrentUser;
            string SubKeyPath = @"Software\Microsoft\Windows\CurrentVersion\Internet Settings";
            RegistryKey optionKey = regKey.OpenSubKey(SubKeyPath, true);
            if (optionKey == null)
            {
                MessageBox.Show(@"注册表损坏，请修复\nHKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings");
                return;
            }

            //更改健值，设置代理，
            try
            {
                optionKey.SetValue("ProxyEnable", 1);
                optionKey.SetValue("ProxyName", proxy.name);
                optionKey.SetValue("ProxyServer", proxy.ip);
                optionKey.SetValue("ProxyOverride", string.IsNullOrEmpty(proxy.filter) ? "<local>" : (proxy.filter + ";<local>"));
                optionKey.SetValue("DisablePasswordCaching", 0);
            }
            catch
            {
                MessageBox.Show("代理设置失败");
                return;
            }

            ProxyStatus = "1";
            CurrentProxy = proxy;

            //激活代理设置
            try
            {
                SafeNativeMethods.InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
                SafeNativeMethods.InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0);
            }
            catch
            {
                MessageBox.Show("代理激活失败");
                return;
            }

            ShowProxy();
            RefreshProxy();
        }

        /// <summary>
        /// 关闭代理服务器
        /// </summary>
        private void CloseProxy()
        {
            //打开注册表
            RegistryKey regKey = Registry.CurrentUser;
            string SubKeyPath = @"Software\Microsoft\Windows\CurrentVersion\Internet Settings";
            RegistryKey optionKey = regKey.OpenSubKey(SubKeyPath, true);
            if (optionKey == null)
            {
                MessageBox.Show(@"注册表损坏，请修复\nHKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings");
                return;
            }

            //更改健值，设置代理
            try
            {
                optionKey.SetValue("ProxyEnable", 0);
            }
            catch
            {
                MessageBox.Show("代理设置失败");
                return;
            }

            ProxyStatus = "0";

            //激活代理设置
            try
            {
                SafeNativeMethods.InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
                SafeNativeMethods.InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0);
            }
            catch
            {
                MessageBox.Show("代理激活失败");
                return;
            }

            ShowProxy();
            RefreshProxy();
        }

        private bool ReadProxy(string ProxyServer)
        {
            string Status = "0";
            string Server = "";
            RegistryKey regKey = Registry.CurrentUser;
            string SubKeyPath = @"Software\Microsoft\Windows\CurrentVersion\Internet Settings";
            RegistryKey optionKey = regKey.OpenSubKey(SubKeyPath, true);
            if (optionKey == null)
            {
                MessageBox.Show(@"注册表损坏，请修复\nHKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings");
                return false;
            }

            try
            {
                Status = optionKey.GetValue("ProxyEnable").ToString();
            }
            catch
            {
                return false;
            }
            if (Status != "1") return false;
            try
            {
                Server = optionKey.GetValue("ProxyServer").ToString();
            }
            catch
            {
                return false;
            }
            if (ProxyServer == Server) return true;
            else return false;
        }

        private void RefreshProxy()
        {
            foreach (Button btn in button)
            {
                if (ProxyStatus=="1" && btn.Name == CurrentProxy.name)
                {
                    btn.Text = "关闭" + btn.AccessibleName;
                }
                else
                {
                    btn.Text = "启用" + btn.AccessibleName;
                }
            }

            for (int i = 1; i < this.ToolStripMenuItem_Setting.DropDownItems.Count; i++)
            {
                if (ProxyStatus == "1" && this.ToolStripMenuItem_Setting.DropDownItems[i].Name == CurrentProxy.name)
                {
                    this.ToolStripMenuItem_Setting.DropDownItems[i].Text = "关闭" + this.ToolStripMenuItem_Setting.DropDownItems[i].Name;
                }
                else
                {
                    this.ToolStripMenuItem_Setting.DropDownItems[i].Text = "启用" + this.ToolStripMenuItem_Setting.DropDownItems[i].Name;
                }
            }
        }

        #endregion

        #region Method

        private List<string> GetMacAddress()
        {
            List<string> mac = new List<string>();
            NetworkInterface[] NetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface NetworkIntf in NetworkInterfaces)
            {
                if (NetworkIntf.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
                {
                    mac.Add(NetworkIntf.GetPhysicalAddress().ToString().ToUpper());
                }
            }
            return mac;
        }

        #endregion

        #region Event

        private void Button_Click(object sender, EventArgs e)
        {
            string name=((Button)sender).AccessibleName;

            foreach (Proxy proxy in PrivateProxy)
            {
                if (proxy.name == name)
                {
                    if (ProxyStatus=="1" && proxy.name == CurrentProxy.name) CloseProxy();
                    else SetProxy(proxy);
                }
            }
        }

        private void ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string name = ((ToolStripMenuItem)sender).Name;

            foreach (Proxy proxy in PrivateProxy)
            {
                if (proxy.name == name)
                {
                    if (ProxyStatus == "1" && proxy.name == CurrentProxy.name) CloseProxy();
                    else SetProxy(proxy);
                }
            }
        }

        private void ToolStripMenuItem_About_Click(object sender, EventArgs e)
        {
            MessageBox.Show("IE代理配置工具V1.0", "萍乡互通");
        }

        private void ToolStripMenuItem_Show_Click(object sender, EventArgs e)
        {
            this.Visible = true;
            this.WindowState = FormWindowState.Normal;
        }

        private void ToolStripMenuItem_Exit_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("您确认要退出吗？", "友情提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
            {
                Application.Exit();
            }
        }

        private void lblProxyStatus_SizeChanged(object sender, EventArgs e)
        {
            Point p = new Point();
            p.X = (this.ClientSize.Width - this.lblProxyStatus.Width) / 2;
            p.Y = this.lblProxyStatus.Location.Y;
            this.lblProxyStatus.Location = p;
        }

        #endregion
    }

    public struct Proxy
    {
        public string name;
        public string ip;
        public string filter;
    }

    [SuppressUnmanagedCodeSecurityAttribute]
    internal static class SafeNativeMethods
    {
        [DllImport(@"wininet", SetLastError = true, CharSet = CharSet.Auto, EntryPoint = "InternetSetOption", CallingConvention = CallingConvention.StdCall)]
        public static extern bool InternetSetOption(IntPtr hInternet, int dmOption, IntPtr lpBuffer, int dwBufferLength);

        [DllImport("user32")]
        public static extern bool AnimateWindow(IntPtr hwnd, int dwTime, int dwFlags);
    }
}
